/*
 * TOSECommands.cpp
 *
 * This file is a part of TermOSEmulator.
 *
 * Written by Peter Winchester <wincsoft_pw@outlook.com>
 * Copyright (C) 2021 Peter Winchester.
 *
 * TermOSEmulator is free software, follows the GNU General
 * Public License.
 *
 * NOTE: TermOSEmulator requires Windows API, so it can only
 * run on the Windows.
 *
 */

#include "TOSECommands.h"

CmdFunc cmdOpt[NUM_COMMANDS] = {
    pause, exitSys, ls, cd, mkdir, rmdir, view, help, apt, rmf};

string cmdName[NUM_COMMANDS] = {
    "pause", "exit", "ls", "cd", "mkdir", "rmdir", "view", "help", "apt", "rmf"};

int pause(vector<string> args)
{
    /* 检查参数，此命令不需要参数 */
    if (args.size())
    {
        printf("The command 'pause' doesn't need any parameter.\n");
        return 0;
    }
    printf("Press any key to continue...");
    getch();
    printf("\n");
    return 1;
}

int exitSys(vector<string> args)
{
    /* 检查参数，此命令不需要参数 */
    if (args.size())
    {
        printf("The command 'exit' doesn't need any parameter.\n");
        return 0;
    }
    toseRunning = false;
    return 1;
}

int ls(vector<string> args)
{
    /* 检查参数，此命令不需要参数 */
    if (args.size())
    {
        printf("The command 'ls' doesn't need any parameter.\n");
        return 0;
    }
	
    /* 如果当前目录不是根目录（/），那么要输出上级目录 */
    if (dirCrt != dirRoot)
    {
        color(9);
        printf(".. ");
        color(7);
    }
	
    /* 显示当前目录下的子目录 */
    color(9);
    for (int i = 0; i < dirCrt->dirChild.size(); i++)
    {
        cout << dirCrt->dirChild[i]->name << " ";
        if ((i + 1) % 5 == 0) printf("\n");
    }
	
    /* 显示当前目录下的文件 */
    color(7);
    for (int i = 0; i < dirCrt->file.size(); i++)
    {
        if (dirCrt->file[i].type == "exe") //可执行文件用另一种颜色
        {
            color(10);
            cout << dirCrt->file[i].name << "." << dirCrt->file[i].type << " ";
            color(7);
        }
        else cout << dirCrt->file[i].name << "." << dirCrt->file[i].type << " ";
        if ((i + 1) % 5 == 0) printf("\n");
    }
    cout << endl;
    return 1;
}

int cd(vector<string> args)
{
    /* 检查参数，此命令需要一个参数 */
    if (args.size() == 0)
    {
        printf("The command 'cd' needs a parameter.\n");
        printf("Type 'help cd' for help.\n");
        return 0;
    }
    if (args.size() > 1)
    {
        printf("The parameters are too many.\n");
        printf("Type 'help cd' for help.\n");
        return 0;
    }
    if (!goToDir(args[0])) //定位到该目录
    {
        printf("Directory not found.\n");
        return 0;
    }
    return 1;
}

int mkdir(vector<string> args)
{
    /* 检查参数，此命令需要一个参数 */
    if (args.size() == 0)
    {
        printf("The command 'mkdir' needs a parameter.\n");
        printf("Type 'help mkdir' for help.\n");
        return 0;
    }
    if (args.size() > 1)
    {
        printf("The parameters are too many.\n");
        printf("Type 'help mkdir' for help.\n");
        return 0;
    }
    if (!createNewDir(args[0])) return 0;
    return 1;
}

int rmdir(vector<string> args)
{
    /* 检查参数，此命令需要一个参数 */
    if (args.size() == 0)
    {
        printf("The command 'rmdir' needs a parameter.\n");
        printf("Type 'help rmdir' for help.\n");
        return 0;
    }
    if (args.size() > 1)
    {
        printf("The parameters are too many.\n");
        printf("Type 'help rmdir' for help.\n");
        return 0;
    }
	
    /* 获取目标路径 */
    string dir;
    for (int i = 0; i < strlen(systemRootPath); i++)
        dir.push_back(systemRootPath[i]);
    for (int i = 1; i < pathCrt.size(); i++)
    {
        dir += pathCrt[i];
        dir += "/";
    }
    dir += args[0];
    dir += "/";
	
    /* 在 Windows 上删除 */
    if (!delDir(dir))
    {
        printf("Error! Please check the directory in Windows.\n");
        return 0;
    }
	
    /* 查找目录 */
    for (int i = 0; i < dirCrt->dirChild.size(); i++)
    {
        if (dirCrt->dirChild[i]->name == args[0])
        {
            /* 在 TOSE 上删除 */
            for (int j = i; j < dirCrt->dirChild.size() - 1; j++)
                dirCrt->dirChild[j] = dirCrt->dirChild[j + 1];
            dirCrt->dirChild.pop_back();
            updateExplorer(); //更新数据
            return 1;
        }
    }
    printf("Error! Cannot find the directory.\n"); //未找到指定目录
    return 0;
}

int rmf(vector<string> args)
{
    /* 检查参数，此命令需要一个参数 */
    if (args.size() == 0)
    {
        printf("The command 'rmf' needs a parameter.\n");
        printf("Type 'help rmf' for details.\n");
        return 0;
    }
    if (args.size() > 1)
    {
        printf("The parameters are too many.\n");
        printf("Type 'help rmf' for details.\n");
        return 0;
    }

    /* 获取文件名称和类型 */
    string nameReq, typeReq;
    int pos = args[0].length() - 1;
    while (pos >= 0 & args[0][pos] != '.') pos--;
    for (int i = pos + 1; i < args[0].length(); i++) typeReq.push_back(args[0][i]);
    for (int i = 0; i < pos; i++) nameReq.push_back(args[0][i]);

    /* 检查文件是否存在 */
    string dir;
    for (int i = 0; i < strlen(systemRootPath); i++)
        dir.push_back(systemRootPath[i]);
    for (int i = 1; i < pathCrt.size(); i++)
    {
        dir += pathCrt[i];
        dir += "/";
    }
    dir += args[0];
    FILE *find = fopen(dir.c_str(), "r");
    if (find == NULL)
    {
        printf("Can't find the file on Windows!\n");
        printf("Please check the current directory.\n");
        return 0;
    }
    fclose(find);
    if (!removeFile(nameReq, typeReq))
    {
        printf("Cannot find the file.\n");
        return 0;
    }

    /* 删除文件 */
    string cmd = "del \"";
    for (int i = 0; i < dir.length(); i++) if (dir[i] == '/') dir[i] = '\\';
    cmd += dir;
    cmd += "\"";
    int res = system(cmd.c_str());
    return res == 0;
}

int view(vector<string> args)
{
    /* 检查参数，此命令需要一个参数 */
    if (args.size() == 0)
    {
        printf("The command 'view' needs a parameter.\n");
        printf("Type 'help view' for help.\n");
        return 0;
    }
    if (args.size() > 1)
    {
        printf("The parameters are too many.\n");
        printf("Type 'help view' for help.\n");
        return 0;
    }
    /* 获取目标文件的名称和类型 */
    string name = args[0], type;
    while (name.length() > 0 && name[name.length() - 1] != '.')
    {
        type.push_back(name[name.length() - 1]);
        name.pop_back();
    }
    name.pop_back();
    int l = 0, r = type.length() - 1;
    while (l < r)
    {
        swap(type[l], type[r]);
        l++, r--;
    }
    /* 查找目标文件 */
    bool find = false;
    for (int i = 0; i < dirCrt->file.size(); i++)
    {
        if (dirCrt->file[i].name == name && dirCrt->file[i].type == type)
        {
            find = true;
            break;
        }
    }
    if (find == false) //未找到目标文件
    {
        printf("Cannot find the file.\n");
        return 0;
    }
    /* 获取目标文件在 Windows 上的目录 */
    string dir;
    for (int i = 0; i < strlen(systemRootPath); i++)
    {
        dir.push_back(systemRootPath[i]);
    }
    for (int i = 1; i < pathCrt.size(); i++)
    {
        dir += pathCrt[i];
        dir.push_back('/');
    }
    dir += name;
    dir.push_back('.');
    dir += type;
    /* 在 Windows 上查找目标文件 */
    FILE *fin = fopen(dir.c_str(), "r");
    if (fin == NULL) //不能打开该文件，可能是该文件未找到
    {
        printf("Error! Please check the file on Windows!\n");
        return 0;
    }
    /* 从 Windows 读取目标文件 */
    char cGet;
    while (fscanf(fin, "%c", &cGet) == 1)
    {
        /* 需要特殊处理'\r'字符 */
        if (cGet == '\r') printf("\n");
        else printf("%c", cGet);
    }
    fclose(fin);
    return 1;
}

int help(vector<string> args)
{
	/*
	  检查参数。这个命令比较特殊，它可以不带参数。
	  但如果带参数，那么参数就必须是命令名称。
	*/
    if (args.size() == 0) //没带参数
    {
        /* 获取 Windows 上的路径 */
        string dir;
        for (int i = 0; i < strlen(systemRootPath); i++)
            dir.push_back(systemRootPath[i]);
        dir += "bin/help/help.txt";

        /* 查找帮助文件 */
        FILE *fin = fopen(dir.c_str(), "r");
        if (fin == NULL) //未找到帮助文件
        {
            printf("Error! Help file ont found.\n");
            return 0;
        }
        char cGet;
        while (fscanf(fin, "%c", &cGet) == 1)
        {
            /* 特殊处理'\r'字符 */
            if (cGet == '\r')printf("\n");
            else printf("%c", cGet);
        }
        fclose(fin);
        return 1;
    }
    else if (args.size() == 1) //带了一个参数
    {
        /* 获取路径 */
        string dir;
        for (int i = 0; i < strlen(systemRootPath); i++)
            dir.push_back(systemRootPath[i]);
        dir += "bin/help/";

        /* 查找命令 */
        bool find = false;
        for (int i = 0; i < NUM_COMMANDS; i++)
        {
            if (cmdName[i] == args[0])
            {
                dir += args[0];
                dir += ".txt";
                find = true;
                break;
            }
        }
        if (!find) //命令未找到
        {
            printf("Error! Command '");
            cout << args[0];
            printf("' not found.\n");
            return 0;
        }

        /* 查找文件 */
        FILE *fin = fopen(dir.c_str(), "r");
        if (!fin) //未找到文件
        {
            printf("Error! File not found.\n");
            return 0;
        }
        char cGet;
        while (fscanf(fin, "%c", &cGet) == 1)
        {
            /* 处理'\r'字符 */
            if (cGet == '\r') printf("\n");
            else printf("%c", cGet);
        }
        fclose(fin);
        return 1;
    }
    printf("Error! The parameters are too many.\n");
    return 0;
}

int apt(vector<string> args)
{
    /* 检查参数，这个命令需要一个参数 */
    if (args.size() == 0)
    {
        printf("Error! Command 'apt' needs an argument.\n");
        return 0;
    }
    if (args.size() > 1)
    {
        printf("Error! The parameters are too many.\n");
        return 0;
    }

    /* 参数的数量合法 */
    if (args[0] == "get") return installApp();
    else if (args[0] == "remove") return removeApp();
    else if (args[0] == "list") return listApps();
    else if (args[0] == "autoremove") return autoRemove();
    printf("The command 'apt' doesn't have the argument '");
    cout << args[0];
    printf("'.\n");
    return 0; //参数错误，返回0
}
